%% @author Mochi Media <dev@mochimedia.com>
%% @copyright 2010 Mochi Media <dev@mochimedia.com>

%% @doc Web server for test1.

% Strong test: 400 mbit, 2000 (catalina side) + 5000 (client side) = 7000 open sockets
% 3 hours uptime - beam.smp process bloated to 2.5Gbyte
% java: 36% cpu, proxy process: 43% cpu

-module(test1_web).
-author("Mochi Media <dev@mochimedia.com>").

% enable native compiler
-compile([debug_info, {hipe,o3}]).

-export([start/1, stop/0, loop/2]).



%% External API

start(Options) ->
    {DocRoot, Options1} = get_option(docroot, Options),
    Loop = fun (Req) ->
                   ?MODULE:loop(Req, DocRoot)
           end,

    mochiweb_http:start([{name, ?MODULE}, {loop, Loop}, {backlog, 1024} | Options1]).

stop() ->
    mochiweb_http:stop(?MODULE).

loop(Req, DocRoot) ->
    "/" ++ Path = Req:get(path),
    try
        loop_safe(Req, DocRoot)
    catch
        Type:What ->
            Report = ["web request failed",
                      {path, Path},
                      {type, Type}, {what, What},
                      {trace, erlang:get_stacktrace()}],
            error_logger:error_report(Report),
            Req:respond({500, [{"Content-Type", "text/plain"}],
                         "request failed, sorry\n"})
    end.


loop_safe(Req, DocRoot) ->
    "/" ++ Path = Req:get(path),
    case Req:get(method) of
        Method when Method =:= 'GET'; Method =:= 'HEAD' ->
            case Path of
                _ ->
                    Req:serve_file(Path, DocRoot)
            end;
        'POST' ->
            case Path of
                "ajaxpost" ->
                    Data = Req:parse_post(),
                    Pid = erlang:binary_to_term(base64:decode(proplists:get_value("pid",Data))),
                    X = list_to_integer(proplists:get_value("x",Data)),
                    Y = list_to_integer(proplists:get_value("y",Data)),

                    Ans = test1_game_sess:human_move(Pid,X,Y),
                    Result = {struct,Ans},

                    DataOut = mochijson2:encode(Result),
                    %io:format("ajaxpost ret ~p~n",[DataOut]),
                    Req:ok({"application/json", [], [DataOut]});

                "init_field" ->
                    {ok,GameSess} = test1_game_sess_sup:start_child(),
                    io:format("new GameSess ~w~n",[GameSess]),
                    Parms = gen_server:call(GameSess,init_field, 30000),
                    Result = {struct, [ { pid, base64:encode(erlang:term_to_binary(GameSess)) } | Parms]},
                    DataOut = mochijson2:encode(Result),
                    %io:format("init_field ret ~p~n",[DataOut]),
                    Req:ok({"application/json", [], [DataOut]});

                _ ->
                    Req:not_found()
            end;
        _ ->
            Req:respond({501, [], []})
    end.


%% Internal API

get_option(Option, Options) ->
    {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.

%%
%% Tests
%%
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").

you_should_write_a_test() ->
    ?assertEqual(
       "No, but I will!",
       "Have you written any tests?"),
    ok.

-endif.
